// @import
import HeroCtrl from "./HeroCtrl";
import MyCoroutine from "../comm/base/MyCoroutine";
import Time from "../comm/base/Time";

// @const
const SP_ANIM_RUN = "Run";
const SP_ANIM_STAND = "Stand";

/**
 * 移动到指定位置
 * 
 * @param SELF this 指针
 * @param oToWorldPos 世界位置
 */
export function __moveTo(SELF: HeroCtrl, oToWorldPos: cc.Vec2): void {
    if (null != SELF._strMoveTo_XCID) {
        MyCoroutine.stopCoroutine(SELF._strMoveTo_XCID);
    }

    SELF._strMoveTo_XCID = MyCoroutine.startCoroutine(
        __moveTo_XC(SELF, oToWorldPos)
    );
}

/**
 * ( 协程方式 ) 移动到指定位置
 * 
 * @param SELF this 指针
 * @param oToWorldPos 世界位置
 * @returns 生成器
 */
function* __moveTo_XC(SELF: HeroCtrl, oToWorldPos: cc.Vec2): Generator<boolean> {
    if (null == SELF || 
        SELF._nCurrHP <= 0 ||
        null == oToWorldPos) {
        yield false;
        return;
    }

    // 获取相对位置
    let oToParentPos: cc.Vec2 = SELF.node.parent.convertToNodeSpaceAR(oToWorldPos);

    if (Math.abs(oToParentPos.x - SELF.node.x) <= 16 && 
        Math.abs(oToParentPos.y - SELF.node.y) <= 16) {
        // 移动范围太小了,
        // 就不动了
        yield false;
        return;
    }

    // 获取 Spine 骨骼控件
    let oSpSkeleton = SELF.node.getComponentInChildren(sp.Skeleton);

    if (oToParentPos.x < SELF.node.x && 
        SELF.node.scaleX > 0) {
        // 转头向左走,
        SELF.node.scaleX = -1;
        cc.find("Holder_NameAndHP", SELF.node).scaleX = -1;
    }

    if (oToParentPos.x > SELF.node.x && 
        SELF.node.scaleX < 0) {
        // 转头向右走,
        SELF.node.scaleX = +1;
        cc.find("Holder_NameAndHP", SELF.node).scaleX = +1;
    }

    let oTe0: sp.spine.TrackEntry = oSpSkeleton.getCurrent(0);

    if (null == oTe0 || 
        null == oTe0.animation || 
        SP_ANIM_RUN != oTe0.animation.name) {
        // 如果不是 Run 动画,
        oTe0 = oSpSkeleton.setAnimation(0, SP_ANIM_RUN, true);
    }

    // 获取 X 和 Y 的距离
    let nDistanceX: number = oToParentPos.x - SELF.node.x;
    let nDistanceY: number = oToParentPos.y - SELF.node.y;
    // 计算方向
    let nDirX: number = nDistanceX < 0 ? -1 : +1;
    let nDirY: number = nDistanceY < 0 ? -1 : +1;

    // 通过反正切公式计算角度
    let nAbsAngle: number = Math.abs(Math.atan(nDistanceY / nDistanceX));

    // 计算 X 和 Y 上的速度
    const RUN_SPEED: number = 240;
    let nSpeedX: number = Math.cos(nAbsAngle) * RUN_SPEED;
    let nSpeedY: number = Math.sin(nAbsAngle) * RUN_SPEED;

    for (; ; yield true) {
        if (Math.abs(SELF.node.x - oToParentPos.x) <= 10 && 
            Math.abs(SELF.node.y - oToParentPos.y) <= 10) {
            // 如果已经非常接近目标位置了,
            break;
        }

        // 执行移动过程
        SELF.node.x += nSpeedX * Time.getDeltaTime() * nDirX;
        SELF.node.y += nSpeedY * Time.getDeltaTime() * nDirY;
        SELF.node.zIndex = -SELF.node.y;
    }

    // 强制结束前一动画
    oTe0.animationEnd = oTe0.animationLast;
    oTe0.loop = false;

    // 设置站立动画
    let oTe1: sp.spine.TrackEntry = oSpSkeleton.addAnimation(0, SP_ANIM_STAND, true);
    oTe1.mixDuration = 0.2;

    yield false;
}
